//---------------------------------------------------------------------
// File: HostConductorStep.cs
// 
// Summary: 
//
//---------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//---------------------------------------------------------------------

namespace Microsoft.Services.BizTalkApplicationFramework.BizUnit
{
	using System;
	using System.Xml;
	using System.Management;
	using Microsoft.Services.BizTalkApplicationFramework.BizUnit;

	/// <summary>
	/// The HostConductorStep test step maybe used to start or stop a BizTalk host
	/// </summary>
	/// 
	/// <remarks>
	/// The following shows an example of the Xml representation of this test step.
	/// 
	/// <code escaped="true">
    ///	<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.HostConductorStep, Microsoft.Services.BizTalkApplicationFramework.BizUnit.BizTalkSteps">
	///		<Action>start|stop</Action>
    ///		<HostInstanceName>BizTalkServerApplication</HostInstanceName>
    ///		<Server>RecvHost</Server>
    ///     <Logon>zeus\\administrator</Logon>
    ///     <PassWord>appollo*1</PassWord>
    ///     <GrantLogOnAsService>true</GrantLogOnAsService>
	///	</TestStep>
	///	</code>
	///	
	///	<list type="table">
	///		<listheader>
	///			<term>Tag</term>
	///			<description>Description</description>
	///		</listheader>
	///		<item>
	///			<term>HostInstanceName</term>
	///			<description>The name of the host instance to start|stop</description>
	///		</item>
	///		<item>
	///			<term>Action</term>
    ///			<description>A value of start or stop<para>(start|stop)</para></description>
	///		</item>
    ///		<item>
    ///			<term>Server</term>
    ///			<description>The server where the Biztalk host instance is running (optional)</description>
    ///		</item>
    ///		<item>
    ///			<term>Logon</term>
    ///			<description>String containing the logon information used by the host instance (optional - unless Server is supplied)</description>
    ///		</item>
    ///		<item>
    ///			<term>PassWord</term>
    ///			<description>String containing the password for the host (optional - unless Logon is supplied)</description>
    ///		</item>
    ///		<item>
    ///			<term>GrantLogOnAsService (optional - unless Logon is supplied)</term>
    ///			<description>Boolean determining whether the 'Log On As Service' privilege should be automatically granted to the specified logon user or not. This flag only has effect when the HostType property is set to In-process</description>
    ///		</item>
    ///	</list>
	///	</remarks>	
	public class HostConductorStep : ITestStep
	{
		/// <summary>
		/// ITestStep.Execute() implementation
		/// </summary>
		/// <param name='testConfig'>The Xml fragment containing the configuration for this test step</param>
		/// <param name='context'>The context for the test, this holds state that is passed beteen tests</param>
		public void Execute(XmlNode testConfig, Context context)
		{
			string action = context.ReadConfigAsString( testConfig, "Action");
            string hostName = context.ReadConfigAsString(testConfig, "HostInstanceName");
            string server = context.ReadConfigAsString(testConfig, "Server", true);
		    string logon = context.ReadConfigAsString(testConfig, "Logon", true);
            string passWord = context.ReadConfigAsString(testConfig, "PassWord", true);
            bool grantLogOnAsService = context.ReadConfigAsBool(testConfig, "GrantLogOnAsService", true);

            ManagementObject mo = GetHostInstanceWmiObject(server, hostName);

			using(mo)
			{
			    if (action.ToLower() == "start")
				{
                    if (null != logon && logon.Length > 0)
                    {
                        object[] creds = new object[3];
                        creds[0] = logon;
                        creds[1] = passWord;
                        creds[2] = grantLogOnAsService;
                        mo.InvokeMethod("Install", creds);
                    }

                    if (mo["ServiceState"].ToString() == "1")
                    {
                        mo.InvokeMethod("Start", null);
                        context.LogInfo("BizTalk Host Started.");
                    }
                    else
                    {
                        context.LogInfo("BizTalk Host is Started.");
                    }
				}

				if ( action.ToLower() =="stop")
				{
                    if (mo["ServiceState"].ToString() != "0")
                    {
                        mo.InvokeMethod("Stop", null);
                        context.LogInfo("BizTalk Host Stopped.");
                    }
                    else
                    {
                        context.LogInfo("BizTalk Host is Stopped.");
                    }
				}				
			}
		}

		private static ManagementObject GetHostInstanceWmiObject(string server, string hostName)
		{
            // 2 represents an isolated host and 1 represents an in-process hosts, only an in-process 
            // can be stopped...
			int hostType = 1;

			ManagementObjectSearcher searcher = new ManagementObjectSearcher();
            ManagementScope scope;

            if (null == server)
            {
                scope = new ManagementScope("root\\MicrosoftBizTalkServer");
            }
            else
            {
                scope = new ManagementScope("\\\\" + server + "\\root\\MicrosoftBizTalkServer");
            }

			searcher.Scope = scope;
		
			// Build a Query to enumerate the MSBTS_hostInstance instances 
			SelectQuery query = new SelectQuery(); 
			query.QueryString = String.Format( "SELECT * FROM MSBTS_HostInstance where HostName='"+ hostName +"' AND HostType=" + hostType.ToString() );

			// Set the query for the searcher.
			searcher.Query = query;

			// Execute the query and determine if any results were obtained.
			ManagementObjectCollection queryCol = searcher.Get();			
			ManagementObjectCollection.ManagementObjectEnumerator me = queryCol.GetEnumerator();
			me.Reset();

			if ( me.MoveNext() )
			{
				return (ManagementObject)me.Current;
			}
			else
			{
				throw new ApplicationException(string.Format("The WMI object for the Host Instance:{0} could not be retrieved.", hostName ));
			}
		}
	}
}

